package com.loto.insurance.oem.web.controller;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;

import com.alipay.config.AlipayConfig;
import com.alipay.util.AlipayNotify;
import com.alipay.util.AlipaySubmit;
import com.loto.insurance.oem.web.authority.OEMAuthority;
import com.loto.insurance.oem.web.entity.AlipayReturn;
import com.loto.insurance.oem.web.entity.CustFeeInit;
import com.loto.insurance.oem.web.entity.OrderInfo;
import com.loto.insurance.oem.web.entity.SessionUser;
import com.loto.insurance.oem.web.entity.config.OEMConfig;
import com.loto.insurance.oem.web.enumeration.ConfigFileEnum;
import com.loto.insurance.oem.web.enumeration.PayChannelEnum;
import com.loto.insurance.oem.web.enumeration.PayForEnum;
import com.loto.insurance.oem.web.service.AlipayReturnService;
import com.loto.insurance.oem.web.service.CustFeeFlowService;
import com.loto.insurance.oem.web.service.CustFeeInitService;
import com.loto.insurance.oem.web.service.CustInfoService;
import com.loto.insurance.oem.web.service.OrderInfoService;
import com.loto.insurance.oem.web.service.common.PolicyOrder;
import com.loto.insurance.oem.web.utils.Config;
import com.loto.utils.DateUtils;

@Controller
@SessionAttributes("oem_user")
public class PayController {
  @Autowired
  OrderInfoService orderInfoService;

  @Autowired
  CustInfoService custInfoService;

  @Autowired
  PolicyOrder policyOrder;

  @Autowired
  AlipayReturnService alipayReturnService;

  @Autowired
  CustFeeInitService custFeeInitService;

  @Autowired
  CustFeeFlowService custFeeFlowService;

  @OEMAuthority
  @RequestMapping(value = "/order/pay", method = RequestMethod.GET)
  public String orderPay(
	  @RequestParam(value = "id", required = true) long orderId,
	  HttpServletRequest request, Model model,
	  @ModelAttribute("oem_user") SessionUser sessionUser) {
	OrderInfo orderInfo = orderInfoService.findOrderPayInfoByCust(orderId,
	    sessionUser.getUserId());
	if (orderInfo != null) {
	  model.addAttribute("order", orderInfo);
	  model.addAttribute("usefulFee",
		  custInfoService.getUsefulfee(sessionUser.getUserId()));
	  OEMConfig configFile = Config.getConfigFile(request,
		  ConfigFileEnum.OEMCONFIG, OEMConfig.class);
	  BigDecimal rate = new BigDecimal(0.012);
	  if (configFile != null)
		rate = configFile.getOemPayAccount().getAlipay().getAccount().getRate();
	  BigDecimal fee = orderInfo.getOrderRealAmount();
	  BigDecimal payFee = fee.divide(new BigDecimal(1).subtract(rate), 2,
		  BigDecimal.ROUND_UP);
	  model.addAttribute("payFee", payFee);
	  model.addAttribute("orderId", orderId);
	  model.addAttribute("orderType", PayForEnum.ORDER.getIndex());
	  return "pay/order_pay";
	} else {
	  return "error";
	}
  }

  @OEMAuthority
  @RequestMapping(value = "/pay/alipay/redirect", method = RequestMethod.POST)
  public String alipayRedirect(
	  @RequestParam(value = "orderId", required = true) long orderId,
	  @RequestParam(value = "orderType", required = true) int payFor,
	  Model model, HttpServletRequest request,
	  @ModelAttribute("oem_user") SessionUser sessionUser) {
	// 取得支付信息
	CustFeeInit feeInit = null;
	if (payFor == PayForEnum.ORDER.getIndex()) {
	  feeInit = policyOrder.prepairOrder(sessionUser.getUserId(), orderId,
		  PayChannelEnum.ALIPAY);
	}
	if (feeInit != null) {
	  // 发起交易
	  // 支付类型
	  String payment_type = "1";
	  // 必填，不能修改
	  String hosts = request.getServerName();
	  String port = request.getServerPort() == 80 ? "" : ":"
		  + String.valueOf(request.getServerPort());
	  // 服务器异步通知页面路径
	  String notify_url = "http://" + hosts + port + "/pay/alipay/notify";
	  // 需http://格式的完整路径，不能加?id=123这类自定义参数
	  // 页面跳转同步通知页面路径
	  String return_url = "http://" + hosts + port + "/pay/alipay/return";
	  // 需http://格式的完整路径，不能加?id=123这类自定义参数，不能写成http://localhost/
	  // 卖家支付宝帐户
	  String seller_email = feeInit.getEmail();
	  // 必填
	  // 商户订单号
	  String out_trade_no = feeInit.getInitOutPayNo();
	  // 商户网站订单系统中唯一订单号，必填
	  // 订单名称
	  String subject = feeInit.getInitOutPayDesc();
	  // 必填
	  // 付款金额
	  String total_fee = feeInit.getInitPayFee().toString();
	  // 必填
	  // 订单描述
	  String body = feeInit.getInitOutPayDesc();
	  // 商品展示地址
	  String show_url = "";
	  // 需以http://开头的完整路径，例如：http://www.xxx.com/myorder.html
	  // 防钓鱼时间戳
	  String anti_phishing_key = "";
	  // 若要使用请调用类文件submit中的query_timestamp函数
	  // 客户端的IP地址
	  String exter_invoke_ip = "";
	  // 非局域网的外网IP地址，如：221.0.0.1

	  // ////////////////////////////////////////////////////////////////////////////////

	  // 把请求参数打包成数组
	  Map<String, String> sParaTemp = new HashMap<String, String>();
	  sParaTemp.put("service", "create_direct_pay_by_user");
	  sParaTemp.put("partner", feeInit.getPartner());
	  sParaTemp.put("_input_charset", AlipayConfig.input_charset);
	  sParaTemp.put("payment_type", payment_type);
	  sParaTemp.put("notify_url", notify_url);
	  sParaTemp.put("return_url", return_url);
	  sParaTemp.put("seller_email", seller_email);
	  sParaTemp.put("out_trade_no", out_trade_no);
	  sParaTemp.put("subject", subject);
	  sParaTemp.put("total_fee", total_fee);
	  sParaTemp.put("body", body);
	  sParaTemp.put("show_url", show_url);
	  sParaTemp.put("anti_phishing_key", anti_phishing_key);
	  sParaTemp.put("exter_invoke_ip", exter_invoke_ip);
	  if (feeInit.getInitRoyaltyFee().compareTo(new BigDecimal(0)) > 0) {
		sParaTemp.put("royalty_type", "10");
		// 收款方Email1^金额1^备注1|付款方Email1^收款方Email2^金额2^备注2|付款方Email2^收款方Email3^金额3^备注3
		/*
	     * sParaTemp.put( "royalty_parameters", feeInit.getInitRoyaltyPayer() +
	     * "^" + feeInit.getInitPayFee().subtract(feeInit.getInitRoyaltyFee()) +
	     * "^" + feeInit.getInitOutPayDesc() + "|" +
	     * feeInit.getInitRoyaltyPayer() + "^" + feeInit.getInitRoyaltyPayee() +
	     * "^" + feeInit.getInitRoyaltyFee() + "^" +
	     * feeInit.getInitRoyaltyMemo());
	     */
		sParaTemp.put("royalty_parameters", feeInit.getInitRoyaltyPayer() + "^"
		    + feeInit.getInitRoyaltyPayee() + "^" + feeInit.getInitRoyaltyFee()
		    + "^" + feeInit.getInitRoyaltyMemo());

	  }

	  // 建立请求
	  String sHtmlText = AlipaySubmit.buildRequest(feeInit.getKey(), sParaTemp,
		  "get", "确认");
	  model.addAttribute("formHtml", sHtmlText);
	  return "pay/alipay/redirect";
	}
	return "error";
  }

  @RequestMapping(value = "/pay/alipay/return", method = RequestMethod.GET)
  public String alipayReturn(HttpServletRequest request, Model model)
	  throws UnsupportedEncodingException {
	// 获取支付宝GET过来反馈信息
	// body=%E5%85%85%E5%80%BC%E6%94%AF%E4%BB%98
	// &buyer_email=1459765902%40qq.com
	// &buyer_id=2088302756017089
	// &exterface=create_direct_pay_by_user
	// &is_success=T
	// &notify_id=RqPnCoPT3K9%252Fvwbh3I75KLs5a2oXmv1YglUf%252BkNamuSJLtMzJGtIIfG41Y0qWrysfN66
	// &notify_time=2013-12-16+09%3A34%3A06
	// &notify_type=trade_status_sync
	// &out_trade_no=201312169338420-29224718
	// &payment_type=1
	// &seller_email=icosuyu%40sina.com
	// &seller_id=2088002020363082
	// &subject=%E5%85%85%E5%80%BC%EF%BC%9A201312169338420-29224718
	// &total_fee=71.29
	// &trade_no=2013121629951508
	// &trade_status=TRADE_SUCCESS
	// &sign=1cd2c37feb07677c7463b394bcdcf87c
	// &sign_type=MD5
	Map<String, String> params = new HashMap<String, String>();
	Map requestParams = request.getParameterMap();
	for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
	  String name = (String) iter.next();
	  String[] values = (String[]) requestParams.get(name);
	  String valueStr = "";
	  for (int i = 0; i < values.length; i++) {
		valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr
		    + values[i] + ",";
	  }
	  // 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
	  valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
	  params.put(name, valueStr);
	}

	// 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
	// 商户订单号
	String out_trade_no = params.get("out_trade_no");

	// 支付宝交易号
	String trade_no = params.get("trade_no");

	// 交易状态
	String trade_status = params.get("trade_status");

	// 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//

	// 计算得出通知验证结果
	OEMConfig configFile = Config.getConfigFile(request,
	    ConfigFileEnum.OEMCONFIG, OEMConfig.class);
	String partner = configFile.getOemPayAccount().getAlipay().getAccount()
	    .getPartner();
	String key = configFile.getOemPayAccount().getAlipay().getAccount()
	    .getSecret();
	boolean verify_result = AlipayNotify.verify(params, partner, key);

	String msg = "<h1 style=\"text-align: center;\">验证失败!</h1>";
	if (verify_result) {// 验证成功
	  // ////////////////////////////////////////////////////////////////////////////////////////
	  // 请在这里加上商户的业务逻辑程序代码

	  // ——请根据您的业务逻辑来编写程序（以下代码仅作参考）——
	  if (trade_status.equals("TRADE_FINISHED")
		  || trade_status.equals("TRADE_SUCCESS")) {
		// 记录返回值
		String buyer_email = params.get("buyer_email") == null ? ""
		    : new String(params.get("buyer_email").getBytes("ISO-8859-1"),
		        "UTF-8");
		String buyer_id = params.get("buyer_id") == null ? "" : params
		    .get("buyer_id");
		String is_success = params.get("is_success") == null ? "" : params
		    .get("is_success");
		String seller_email = params.get("seller_email") == null ? ""
		    : new String(params.get("seller_email").getBytes("ISO-8859-1"),
		        "UTF-8");
		String seller_id = params.get("seller_id") == null ? "" : params
		    .get("seller_id");
		String total_fee = params.get("total_fee") == null ? "0" : params
		    .get("total_fee");
		String notify_time = params.get("notify_time") == null ? ""
		    : new String(params.get("notify_time").getBytes("ISO-8859-1"),
		        "UTF-8");

		AlipayReturn alipayReturn = new AlipayReturn();
		alipayReturn.setReturnAmount(new BigDecimal(total_fee));
		alipayReturn.setReturnBuyerEmail(buyer_email);
		alipayReturn.setReturnBuyerId(buyer_id);
		alipayReturn.setReturnCreateTime(DateUtils.parseDateTime(notify_time));
		alipayReturn.setReturnIsSuc(is_success);
		alipayReturn.setReturnOutPayNo(out_trade_no);
		alipayReturn.setReturnParams(request.getQueryString());
		alipayReturn.setReturnPayNo(trade_no);
		alipayReturn.setReturnPayTime(DateUtils.parseDateTime(notify_time));
		alipayReturn.setReturnSellerEmail(seller_email);
		alipayReturn.setReturnSellerId(seller_id);
		alipayReturn.setReturnTradeStatus(trade_status);
		long returnId = alipayReturnService.insertAlipayReturn(alipayReturn);

		if (returnId > 0
		    && alipayReturn.getReturnAmount().compareTo(new BigDecimal(0)) > 0) {
		  CustFeeInit feeInit = custFeeInitService
			  .findInitByOutPayNo(out_trade_no);
		  if (feeInit != null && feeInit.getInitFlag() == 0
			  && feeInit.getInitPayFee().equals(alipayReturn.getReturnAmount())) {// 未处理
			feeInit.setInitPayNo(trade_no);
			feeInit.setInitCreditedOn(DateUtils.parseDateTime(notify_time));
			if (feeInit.getInitFor() == PayForEnum.ORDER.getIndex()) {
			  if (policyOrder.doPay(feeInit)) {
				int result = custFeeInitService.updateFlagByOutPayNo(
				    out_trade_no, feeInit.getInitCreditedOn(),
				    feeInit.getInitPayNo());
				if (result > 0) {
				  // TODO 通知平台进行投保
				}
				msg = "<h1 style=\"text-align: center;\">支付成功!</h1><p>进入<a href=\"/order/list\">订单查询</a>查看详情</p>";
			  } else
				msg = "<h1 style=\"text-align: center;\">订单已支付!</h1>";
			}
		  }
		}
		// 判断该笔订单是否在商户网站中已经做过处理
		// 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
		// 如果有做过处理，不执行商户的业务程序
	  }

	  // 该页面可做页面美工编辑
	  // msg = "<span style=\"color: Red;\">" + orderNo + "</span>支付成功!";
	  // ——请根据您的业务逻辑来编写程序（以上代码仅作参考）——

	  // ////////////////////////////////////////////////////////////////////////////////////////
	}
	model.addAttribute("msg", msg);
	return "pay/alipay/return";
  }

  @RequestMapping(value = "/pay/alipay/notify", method = RequestMethod.POST)
  public String alipayNotify(HttpServletRequest request, Model model)
	  throws UnsupportedEncodingException {
	// 获取支付宝GET过来反馈信息
	Map<String, String> params = new HashMap<String, String>();
	Map requestParams = request.getParameterMap();
	for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
	  String name = (String) iter.next();
	  String[] values = (String[]) requestParams.get(name);
	  String valueStr = "";
	  for (int i = 0; i < values.length; i++) {
		valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr
		    + values[i] + ",";
	  }
	  // 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
	  valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
	  params.put(name, valueStr);
	}

	// 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
	// 商户订单号
	String out_trade_no = params.get("out_trade_no");

	// 支付宝交易号
	String trade_no = params.get("trade_no");

	// 交易状态
	String trade_status = params.get("trade_status");

	// 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//

	// 计算得出通知验证结果
	OEMConfig configFile = Config.getConfigFile(request,
	    ConfigFileEnum.OEMCONFIG, OEMConfig.class);
	String partner = configFile.getOemPayAccount().getAlipay().getAccount()
	    .getPartner();
	String key = configFile.getOemPayAccount().getAlipay().getAccount()
	    .getSecret();
	boolean verify_result = AlipayNotify.verify(params, partner, key);

	String msg = "error";
	if (verify_result) {// 验证成功
	  // ////////////////////////////////////////////////////////////////////////////////////////
	  // 请在这里加上商户的业务逻辑程序代码

	  // ——请根据您的业务逻辑来编写程序（以下代码仅作参考）——
	  if (trade_status.equals("TRADE_FINISHED")
		  || trade_status.equals("TRADE_SUCCESS")) {
		// 记录返回值
		String buyer_email = params.get("buyer_email") == null ? ""
		    : new String(params.get("buyer_email").getBytes("ISO-8859-1"),
		        "UTF-8");
		String buyer_id = params.get("buyer_id") == null ? "" : params
		    .get("buyer_id");
		String is_success = params.get("is_success") == null ? "" : params
		    .get("is_success");
		String seller_email = params.get("seller_email") == null ? ""
		    : new String(params.get("seller_email").getBytes("ISO-8859-1"),
		        "UTF-8");
		String seller_id = params.get("seller_id") == null ? "" : params
		    .get("seller_id");
		String total_fee = params.get("total_fee") == null ? "0" : params
		    .get("total_fee");
		String create_time = params.get("gmt_create") == null ? ""
		    : new String(params.get("gmt_create").getBytes("ISO-8859-1"),
		        "UTF-8");
		String pay_time = params.get("gmt_payment") == null ? "" : new String(
		    params.get("gmt_payment").getBytes("ISO-8859-1"), "UTF-8");

		AlipayReturn alipayReturn = new AlipayReturn();
		alipayReturn.setReturnAmount(new BigDecimal(total_fee));
		alipayReturn.setReturnBuyerEmail(buyer_email);
		alipayReturn.setReturnBuyerId(buyer_id);
		alipayReturn.setReturnCreateTime(DateUtils.parseDateTime(create_time));
		alipayReturn.setReturnIsSuc(is_success);
		alipayReturn.setReturnOutPayNo(out_trade_no);
		alipayReturn.setReturnParams(request.getQueryString());
		alipayReturn.setReturnPayNo(trade_no);
		alipayReturn.setReturnPayTime(DateUtils.parseDateTime(pay_time));
		alipayReturn.setReturnSellerEmail(seller_email);
		alipayReturn.setReturnSellerId(seller_id);
		alipayReturn.setReturnTradeStatus(trade_status);
		long returnId = alipayReturnService.insertAlipayReturn(alipayReturn);

		if (returnId > 0
		    && alipayReturn.getReturnAmount().compareTo(new BigDecimal(0)) > 0) {
		  CustFeeInit feeInit = custFeeInitService
			  .findInitByOutPayNo(out_trade_no);
		  if (feeInit != null && feeInit.getInitFlag() == 0
			  && feeInit.getInitPayFee().equals(alipayReturn.getReturnAmount())) {// 未处理
			feeInit.setInitPayNo(trade_no);
			feeInit.setInitCreditedOn(DateUtils.parseDateTime(pay_time));
			if (feeInit.getInitFor() == PayForEnum.ORDER.getIndex()) {
			  if (policyOrder.doPay(feeInit)) {
				int result = custFeeInitService.updateFlagByOutPayNo(
				    out_trade_no, feeInit.getInitCreditedOn(),
				    feeInit.getInitPayNo());
				if (result > 0) {
				  // TODO 通知平台进行投保
				}
				msg = "success";
			  } else
				msg = "success";
			}
		  }
		}
		// 判断该笔订单是否在商户网站中已经做过处理
		// 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
		// 如果有做过处理，不执行商户的业务程序
	  }

	  // 该页面可做页面美工编辑
	  // msg = "<span style=\"color: Red;\">" + orderNo + "</span>支付成功!";
	  // ——请根据您的业务逻辑来编写程序（以上代码仅作参考）——

	  // ////////////////////////////////////////////////////////////////////////////////////////
	}
	model.addAttribute("msg", msg);
	return "pay/alipay/notify";
  }

  @OEMAuthority
  @RequestMapping(value = "/pay/balance", method = RequestMethod.POST)
  public String balance(
	  @RequestParam(value = "orderId", required = true) long orderId,
	  @RequestParam(value = "orderType", required = true) int payFor,
	  Model model, @ModelAttribute("oem_user") SessionUser sessionUser) {
	// 取得支付信息
	CustFeeInit feeInit = null;
	if (payFor == PayForEnum.ORDER.getIndex()) {
	  feeInit = policyOrder.prepairOrder(sessionUser.getUserId(), orderId,
		  PayChannelEnum.BALANCE);
	}
	if (feeInit != null) {
	  Calendar calendar = Calendar.getInstance();
	  feeInit.setInitPayNo(feeInit.getInitOutPayNo());
	  feeInit.setInitCreditedOn(calendar.getTime());
	  if (policyOrder.doPay(feeInit)) {
		int result = custFeeInitService.updateFlagByOutPayNo(
		    feeInit.getInitOutPayNo(), feeInit.getInitCreditedOn(),
		    feeInit.getInitPayNo());
		// OEM中将订单实际金额-订单结算金额的金额以余额方式给到OEM的admin账号
		if (result > 0 && custFeeFlowService.insertRoyaltyFeeFlow(feeInit)) {
		  // TODO 通知平台进行投保
		}
	  }
	}
	model
	    .addAttribute(
	        "msg",
	        "<h1 style=\"text-align: center;\">支付成功!</h1><p>进入<a href=\"/order/list\">订单查询</a>查看详情</p>");
	return "pay/alipay/return";
  }
}
